#include "SerialInator.h"


SerialInator::SerialInator(){
	this->_posActual = 0;
	this->_cantBytes = 0;
}

SerialInator::~SerialInator(){
	this->_posActual = 0;
	this->_cantBytes = 0;
}

// Al colocar la posicion actual del buffer que se esta procesando en cero
// se puede utilizar las otras operaciones (serializar/des-serializar)
void SerialInator::reset(){
	this->_posActual = 0;
	this->_cantBytes = 0;
}

void SerialInator::serializar(char* &arrBytes, char c){
	arrBytes[this->_posActual] = c;
	this->_posActual++;
	this->_cantBytes += sizeof(c);
}

void SerialInator::serializar(char* &arrBytes, int valor){
	// Crea un puntero a "bytes" que apunta al valor entero
	char* ptr = reinterpret_cast<char*>(&valor);

	// Asigna los bytes del entero en reversa
	arrBytes[this->_posActual++] = ptr[3];
	arrBytes[this->_posActual++] = ptr[2];
	arrBytes[this->_posActual++] = ptr[1];
	arrBytes[this->_posActual++] = ptr[0];

	this->_cantBytes += sizeof(valor);
}

void SerialInator::serializar(char* &arrBytes, unsigned int valor){
	// Crea un puntero a "bytes" que apunta al valor entero
	char* ptr = reinterpret_cast<char*>(&valor);

	// Asigna los bytes del entero en reversa
	arrBytes[this->_posActual++] = ptr[3];
	arrBytes[this->_posActual++] = ptr[2];
	arrBytes[this->_posActual++] = ptr[1];
	arrBytes[this->_posActual++] = ptr[0];

	this->_cantBytes += sizeof(valor);
}

// Para serializar una cadena primero guarda su tamaño en bytes
void SerialInator::serializar(char* &arrBytes, std::string cadena){

	// Serializa la longitud de la cadena
	serializar(arrBytes, static_cast<int>(cadena.size()));

	// Copia los caracteres al buffer
	char* ptrCadena = &arrBytes[this->_posActual];
	cadena.copy(ptrCadena, cadena.size());
	this->_posActual += cadena.size();

	// Supongo que la cedena esta formada por chars
	this->_cantBytes += cadena.size();
}


void SerialInator::desSerializar(char* arrBytes, char &c){
	c = arrBytes[this->_posActual++];
	this->_cantBytes += sizeof(c);
}

void SerialInator::desSerializar(char* arrBytes, int &valor){
	// Extrae los bytes que forman parte del entero en reversa
	char val[4] = {0};
	val[3] = arrBytes[this->_posActual++];
	val[2] = arrBytes[this->_posActual++];
	val[1] = arrBytes[this->_posActual++];
	val[0] = arrBytes[this->_posActual++];

	// Convierte los bytes en un numero entero
	int* ptr = reinterpret_cast<int*>(val);
	valor = *ptr;

	this->_cantBytes += sizeof(valor);
}

void SerialInator::desSerializar(char* arrBytes, unsigned int &valor){
	// Extrae los bytes que forman parte del entero en reversa
	char val[4] = {0};
	val[3] = arrBytes[this->_posActual++];
	val[2] = arrBytes[this->_posActual++];
	val[1] = arrBytes[this->_posActual++];
	val[0] = arrBytes[this->_posActual++];

	// Convierte los bytes en un numero entero
	unsigned int* ptr = reinterpret_cast<unsigned int*>(val);
	valor = *ptr;

	this->_cantBytes += sizeof(valor);
}

void SerialInator::desSerializar(char* arrBytes, std::string &cadena){
	// Primero extrae la longitud de la cadena
	int tamCadena;
	desSerializar(arrBytes, tamCadena);

	// Extrae la cadena en si
	cadena.assign(&arrBytes[this->_posActual], tamCadena);
	this->_posActual += tamCadena;
	this->_cantBytes += cadena.size();	// Cadena formada por chars
}


void SerialInator::serializar(char* &arrBytes, IRegistro* reg){
	// El comienzo actual del buffer donde se encuentra el dato del registro
	char* buffReg = arrBytes + this->_posActual;

	// Se serializa el registro en el buffer y devuelve la cantidad de bytes, se actualiza la posicion del buffer
	int regSize = reg->serializar(buffReg);
	this->_posActual += regSize ;
	this->_cantBytes += regSize;
}


void SerialInator::desSerializar(char* arrBytes, IRegistro* &reg){
	char* buffReg = arrBytes + this->_posActual;
	int regSize = reg->desSerializar(buffReg);

	this->_posActual += regSize;
	this->_cantBytes += regSize;
}


size_t SerialInator::getBufferSize() const{
	return this->_cantBytes;
}
